﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SosoEngine.Simple.Impl.Utilities
{
    public sealed class ArrayHelper
    {
        /// <summary>
        /// Redims the specified array.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="defaultType">The default type.</param>
        /// <param name="lengths">The lengths.</param>
        /// <returns></returns>
        public static Array Redim(Array array, Type defaultType, params int[] lengths)
        {
            Type t;

            if (array != null)
            {
                t = array.GetType().GetElementType();
            }
            else
            {
                t = defaultType;
            }

            Array newArray = Array.CreateInstance(t, lengths);

            if (array != null)
            {
                int rank = array.Rank;
                if (rank > 2)
                {
                    throw new NotImplementedException("Only support 2 dimension array.");
                }
                if (rank > 1)
                {
                    int minX = array.GetLowerBound(0);
                    int maxX = array.GetUpperBound(0);
                    int minY = array.GetLowerBound(1);
                    int maxY = array.GetUpperBound(1);

                    for (int i = minX; i <= maxX; i++)
                    {
                        for (int j = minY; j <= maxY; j++)
                        {
                            newArray.SetValue(array.GetValue(i, j), i, j);
                        }
                    }
                }
                else
                {
                    Array.Copy(array, newArray, array.Length);
                }
            }

            return newArray;
        }

        public static bool ArrayEquals(Array array1, Array array2)
        {
            bool result = false;

            if (!Object.ReferenceEquals(array1.GetType(), array2.GetType()))
            {
                return result;
            }

            if (array1.Rank != array2.Rank || array1.Rank > 2 || array2.Rank > 2)
            {
                return result;
            }

            if (array1.GetLowerBound(0) != array2.GetLowerBound(0)
                || array1.GetUpperBound(0) != array1.GetUpperBound(0))
            {
                return result;
            }

            int x0,x1,y0,y1;
            
            result = true;

            switch (array1.Rank)
            { 
                case 1:
                    x0 = array1.GetLowerBound(0);
                    x1 = array1.GetUpperBound(0);
                    for (int i = x0; i <= x1; i++)
                    {
                        if (array1.GetValue(i) != array2.GetValue(i))
                        {
                            result = false;
                            break;
                        }
                    }
                    
                    break;
                case 2:
                    x0 = array1.GetLowerBound(0);
                    x1 = array1.GetUpperBound(0);
                    y0 = array1.GetLowerBound(1);
                    y1 = array1.GetUpperBound(1);
                    for (int i = x0; i <= x1; i++)
                    {
                        for (int j = y0; j <= y1; j++)
                        {
                            if (!array1.GetValue(i, j).Equals(array2.GetValue(i, j)))
                            {
                                result = false;
                                goto OUTLINE;
                            }
                        }
                    }
                OUTLINE:
                    break;
            }

            return result;
        }
    }
}
